# app.py

import os
import logging
from datetime import timedelta
from pathlib import Path
from logging.handlers import RotatingFileHandler

from coverage import Coverage
from flask import Flask, jsonify
from flask_cors import CORS
from flask_jwt_extended import JWTManager
from jwt import ExpiredSignatureError

from config.database import db
from jwt import ExpiredSignatureError
from sqlalchemy.exc import SQLAlchemyError
from marshmallow import ValidationError
from config.error_handlers import (
    handle_expired_error,
    handle_database_error,
    handle_validation_error,
    handle_not_found_error,
    handle_method_not_allowed,
    handle_general_error
)
from config.marshmallow_config import ma
from config.app_config import config
from controllers.auth import auth
from controllers.company import company_blueprint
from controllers.role import role_blueprint
from controllers.account import account_blueprint
from utils.auth_utils import bcrypt

def setup_logging(app):
    """配置应用日志系统"""
    # 创建日志目录
    log_dir = Path("logs")
    log_dir.mkdir(exist_ok=True)
    
    # 设置日志格式
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    
    # 文件处理器 - 使用 RotatingFileHandler
    file_handler = RotatingFileHandler(
        'logs/app.log',
        maxBytes=10485760,  # 10MB
        backupCount=10,
        encoding='utf-8'
    )
    file_handler.setFormatter(formatter)
    
    # 根据环境设置日志级别
    if app.config['ENV'] == 'production':
        file_handler.setLevel(logging.ERROR)
        app.logger.setLevel(logging.ERROR)
    else:
        file_handler.setLevel(logging.DEBUG)
        app.logger.setLevel(logging.DEBUG)
    
    # 控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(formatter)
    console_handler.setLevel(logging.DEBUG)
    
    # 清除默认的处理器
    app.logger.handlers.clear()
    
    # 添加处理器到应用logger
    app.logger.addHandler(file_handler)
    app.logger.addHandler(console_handler)
    
    # 设置propagate为False以防止日志重复
    app.logger.propagate = False
    
    # 记录应用启动信息
    app.logger.info(f"Application started in {app.config['ENV']} environment")

def register_extensions(app):
    """注册Flask扩展"""
    # 初始化CORS
    CORS(app, resources={
        r"/*": {
            "origins": app.config.get('CORS_ORIGINS', "*"),
            "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
            "allow_headers": ["Content-Type", "Authorization"]
        }
    })
    
    # 初始化数据库
    db.init_app(app)
    
    # 初始化bcrypt
    bcrypt.init_app(app)
    
    # 初始化JWT
    jwt = JWTManager(app)
    
    # 初始化Marshmallow
    ma.init_app(app)

def register_error_handlers(app):
    """注册所有错误处理器"""
    app.register_error_handler(ExpiredSignatureError, handle_expired_error)
    app.register_error_handler(SQLAlchemyError, handle_database_error)
    app.register_error_handler(ValidationError, handle_validation_error)
    app.register_error_handler(404, handle_not_found_error)
    app.register_error_handler(405, handle_method_not_allowed)
    # 注册通用错误处理器
    app.register_error_handler(Exception, handle_general_error)

def register_blueprints(app):
    """注册蓝图"""
    app.register_blueprint(auth)
    app.register_blueprint(role_blueprint, url_prefix='/api/role')
    app.register_blueprint(account_blueprint, url_prefix='/api/account')
    app.register_blueprint(company_blueprint, url_prefix='/rest_company')

def create_app(config_name=None):
    """应用工厂函数"""
    app = Flask(__name__)
    
    # 确定使用哪个配置
    if not config_name:
        config_name = os.getenv('FLASK_ENV', 'development')
    
    # 从对象加载配置
    app.config.from_object(config[config_name])
    
    # 从环境变量文件加载配置（如果存在）
    env_file = os.getenv('FLASK_ENV_FILE', '.env')
    if os.path.exists(env_file):
        app.config.from_envvar('FLASK_ENV_FILE')
    
    # 设置日志
    setup_logging(app)
    
    # 注册扩展
    register_extensions(app)
    
    # 注册错误处理器
    register_error_handlers(app)
    
    # 注册蓝图
    register_blueprints(app)
    
    # 创建数据库表
    with app.app_context():
        try:
            # db.create_all()
            app.logger.info('Database tables created successfully')
        except Exception as e:
            app.logger.error(f'Error creating database tables: {str(e)}')
    
    return app

# 初始化代码覆盖率工具
cov = Coverage(
    branch=True,
    include='controllers/*',
    omit=['tests/*', 'venv/*']
)

def init_test_app():
    """初始化测试应用"""
    app = create_app('testing')
    return app

# 创建应用实例
app = create_app()

@app.cli.command()
def test():
    """运行单元测试"""
    import unittest
    
    # 启动代码覆盖率收集
    cov.start()
    
    # 运行测试
    tests = unittest.TestLoader().discover('tests')
    test_result = unittest.TextTestRunner(verbosity=2).run(tests)
    
    # 停止代码覆盖率收集并生成报告
    if test_result.wasSuccessful():
        cov.stop()
        cov.save()
        print('Coverage Summary:')
        cov.report()
        basedir = os.path.abspath(os.path.dirname(__file__))
        covdir = os.path.join(basedir, 'coverage')
        cov.html_report(directory=covdir)
        cov.erase()
        return 0
    return 1


if __name__ == '__main__':
    # 获取端口配置，默认为8080
    port = int(os.getenv('FLASK_PORT', 8080))
    
    # 运行应用
    app.run(
        host='0.0.0.0',
        port=port,
        debug=app.config.get('DEBUG', True)
    )